package main

import "fmt"

func main() {
	demo2()
}

/*
 * 数组是具有相同类型的一组已经编号且长度固定的数据项序列
 * 数组长度也是数组类型的一部分，[20]int和[100]int不是同一种类型
 */
func demo1() {
	// 声明一个数组
	// Go语言在声明变量时，都是使用相应类型的零值来初始化变量的
	var array [5]int
	fmt.Println(array)

	// 用具体值来初始化每个元素
	array2 := [5]int{10, 20, 30, 40, 50}
	fmt.Println(array2)

	// 给指定下标指定具体值
	array3 := [5]int{1: 10, 3: 30}
	fmt.Println(array3)

	// 自动推断长度
	array4 := [...]int{10, 20, 30, 40, 50}
	fmt.Println(array4)

	// 访问数组元素
	array5 := [5]int{1, 2, 3, 4, 5}
	for i := 0; i < len(array5); i++ {
		fmt.Printf("Array at index %d is %d\n", i, array5[i])
	}

	// 修改数组元素
	array6 := [5]int{1, 2, 3, 4, 5}
	array6[3] = 99

	// 修改指针数组元素指向的值
	array7 := [5]*int{0: new(int), 1: new(int)}
	*array7[0] = 10
	*array7[1] = 20

	// 多维数组
	array8 := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}}
	fmt.Println(array8)

	// 多维数组初始化指定值
	array9 := [4][2]int{1: {0: 30}, 3: {1: 40}}
	fmt.Println(array9)

	// 传递数组指针给函数
	array10 := [10]int{}
	foo(&array10)
}

// 接收数组指针而不是副本可避免副本创建开销
// 这样的操作结果也可直接反馈到原数组
func foo(array *[10]int) {
	// 业务逻辑
}

func demo2() {
	// 创建数组切片使用make函数
	// 如下，创建一个长度和容量都是5的字符串切片
	slice1 := make([]string, 5)
	fmt.Println(slice1)

	// 创建一个长度为3个元素，容量为5个元素的整型切片
	// 容量为5代表底层数组长度为5，而长度为3代表此切片只能访问3个元素
	// 但是剩下的两个元素可以通过后期操作合并到当前切片中
	slice2 := make([]int, 3, 5)
	fmt.Println(slice2)

	// 切片字面量形式创建切片
	slice3 := []string{"red", "orange", "pink"}
	fmt.Println(slice3)
	slice4 := []int{3, 4, 5, 6}
	fmt.Println(slice4)

	// 空切片|nil切片
	// nil切片在底层数组中包含0个元素，也没有分配任何存储空间
	var slice5 []int
	fmt.Println(slice5)

	// 数组切片
	// slice6[1:3]中的1代表起始索引（含），3代表结束索引（不含）
	// 切片结果为[2, 3]
	slice6 := []int{1, 2, 3, 4, 5, 6}
	new_slice6 := slice6[1:3]
	fmt.Println(new_slice6)

	// 切片扩容
	slice7 := []int{10, 20, 30, 40, 50}
	new_slice7 := slice7[2:4]
	// append()被调用时会返回一个包含修改结果的新切片
	// append()只能增加新切片的长度，容量可能会改变，也可能不会
	new_slice7 = append(new_slice7, 60)
	fmt.Println(new_slice7)

	// 切片限制容量
	slice8 := []int{1, 2, 3, 4}
	// 切片时添加第三个索引，会限制此切片容量大小
	// 在执行append操作时，如果容量满了，会触发扩容操作
	// 扩容后此切片与原数组的底层存储进行了分离
	// 再进行赋值就不会互相影响
	new_slice8 := slice8[1:3:4]
	fmt.Println(slice8, new_slice8)
	new_slice8[1] = 8
	new_slice8 = append(new_slice8, 9)
	new_slice8[1] = 7
	fmt.Println(slice8, new_slice8)
	new_slice8 = append(new_slice8, 9)
	fmt.Println(slice8, new_slice8)
	new_slice8 = append(new_slice8, 9)
	fmt.Println(slice8, new_slice8)
}
